import { is } from 'bpmn-js/lib/util/ModelUtil';

export class PropertiesUtil {
  static updateProperties(modeling: any, element: any, properties: any) {
    if (!element || !properties) {
      console.warn('updateProperties: Missing element or properties');
      return;
    }
    
    try {
      // 创建一个新的属性对象，避免代理对象问题
      const newProperties = Object.fromEntries(
        Object.entries(properties).map(([key, value]) => {
          if (Array.isArray(value)) {
            return [key, [...value]];
          }
          return [key, value];
        })
      );
      
      console.log('Updating properties:', element.id, newProperties);
      modeling.updateProperties(element, newProperties);
    } catch (error) {
      console.error('Failed to update properties:', error);
    }
  }

  static updateFlowableProperty(modeling: any, element: any, propertyName: string, value: any) {
    if (!element || !propertyName) {
      console.warn('updateFlowableProperty: Missing element or propertyName');
      return;
    }
    
    const prefix = 'flowable:';
    const fullPropertyName = `${prefix}${propertyName}`;

    try {
      // 准备更新的属性对象
      const properties: any = {};

      // 如果值为空，则将属性设置为 undefined 来删除它
      if (value === '' || value === null || value === undefined || (Array.isArray(value) && value.length === 0)) {
        properties[fullPropertyName] = undefined;
        console.log(`Removing flowable property: ${fullPropertyName}`);
      } else {
        // 处理数组类型的值
        if (Array.isArray(value)) {
          // 如果是数组类型，将其转换为字符串
          properties[fullPropertyName] = value.filter(item => item && item.trim()).join(',');
        } else {
          properties[fullPropertyName] = String(value).trim();
        }
        console.log(`Setting flowable property: ${fullPropertyName} = ${properties[fullPropertyName]}`);
      }

      // 使用 modeling.updateProperties 来更新
      this.updateProperties(modeling, element, properties);
    } catch (error) {
      console.error(`Failed to update flowable property ${propertyName}:`, error);
    }
  }

  static updateTimerDefinition(modeling: any, element: any, timerType: string, value: string) {
    const bpmnFactory = modeling.bpmnFactory;
    const businessObject = element.businessObject;
    let eventDefinitions = businessObject.eventDefinitions || [];
    let timerDefinition = eventDefinitions.find((def: any) => is(def, 'bpmn:TimerEventDefinition'));

    if (!timerDefinition) {
      timerDefinition = bpmnFactory.create('bpmn:TimerEventDefinition');
      eventDefinitions = [timerDefinition];
    }

    // 清除之前的定时器定义
    delete timerDefinition.timeDate;
    delete timerDefinition.timeDuration;
    delete timerDefinition.timeCycle;

    // 设置新的定时器定义
    const timeDefinition = bpmnFactory.create(`bpmn:FormalExpression`, {
      body: value
    });
    timerDefinition[timerType] = timeDefinition;

    this.updateProperties(modeling, element, {
      eventDefinitions
    });
  }

  static updateMessageDefinition(modeling: any, element: any, messageName: string) {
    const bpmnFactory = modeling.bpmnFactory;
    const businessObject = element.businessObject;
    let eventDefinitions = businessObject.eventDefinitions || [];
    let messageDefinition = eventDefinitions.find((def: any) => is(def, 'bpmn:MessageEventDefinition'));

    if (!messageDefinition) {
      messageDefinition = bpmnFactory.create('bpmn:MessageEventDefinition');
      eventDefinitions = [messageDefinition];
    }

    const message = bpmnFactory.create('bpmn:Message', {
      name: messageName
    });

    messageDefinition.messageRef = message;

    this.updateProperties(modeling, element, {
      eventDefinitions
    });
  }

  static updateConditionExpression(modeling: any, element: any, conditionExpression: string) {
    const bpmnFactory = modeling.bpmnFactory;

    const expression = bpmnFactory.create('bpmn:FormalExpression', {
      body: conditionExpression
    });

    this.updateProperties(modeling, element, {
      conditionExpression: expression
    });
  }

  static setDefaultCondition(modeling: any, element: any, isDefault: boolean) {
    modeling.updateProperties(element.source, { default: isDefault ? element : undefined })
  }

  static updateServiceImplementation(modeling: any, element: any, type: string, value: string) {
    try {
      const properties: any = {
        'flowable:class': null,
        'flowable:expression': null,
        'flowable:delegateExpression': null
      };

      const trimmedValue = value?.trim();
      
      if (trimmedValue) {
        switch (type) {
          case 'class':
            // 验证Java类名格式
            if (!/^[a-zA-Z][a-zA-Z0-9_.]*[a-zA-Z0-9]$/.test(trimmedValue)) {
              console.warn('疑似无效的Java类名格式');
            }
            properties['flowable:class'] = trimmedValue;
            break;
          case 'expression':
            // 验证表达式格式（简单检查）
            if (!trimmedValue.includes('${') && !trimmedValue.includes('}')) {
              console.warn('表达式通常应该包含 ${...} 格式');
            }
            properties['flowable:expression'] = trimmedValue;
            break;
          case 'delegateExpression':
            properties['flowable:delegateExpression'] = trimmedValue;
            break;
          default:
            console.warn(`未知的服务类型: ${type}`);
            return;
        }
      }

      console.log(`Updating service implementation: ${type} = ${trimmedValue}`);
      this.updateProperties(modeling, element, properties);
    } catch (error) {
      console.error('Failed to update service implementation:', error);
    }
  }

  static updateFormProperties(modeling: any, element: any, formProperties: any[]) {
    try {
      const bpmnFactory = modeling.bpmnFactory;
      const businessObject = element.businessObject;
      let extensionElements = businessObject.extensionElements;

      if (!extensionElements) {
        extensionElements = bpmnFactory.create('bpmn:ExtensionElements');
      }

      // 验证表单属性
      const validProperties = formProperties.filter(prop => {
        if (!prop.id || !prop.id.trim()) {
          console.warn('表单属性缺少ID，已跳过');
          return false;
        }
        if (!prop.name || !prop.name.trim()) {
          console.warn(`表单属性 ${prop.id} 缺少名称，已跳过`);
          return false;
        }
        // 验证ID格式（只能包含字母、数字和下划线）
        if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(prop.id)) {
          console.warn(`表单属性ID ${prop.id} 格式不正确，已跳过`);
          return false;
        }
        return true;
      });

      if (validProperties.length === 0) {
        // 如果没有有效属性，删除表单配置
        extensionElements.values = extensionElements.values?.filter(
          (el: any) => el.$type !== 'flowable:FormData'
        ) || [];
      } else {
        const formData = bpmnFactory.create('flowable:FormData');
        const formFields = validProperties.map(prop => {
          return bpmnFactory.create('flowable:FormField', {
            id: prop.id.trim(),
            label: prop.name.trim(),
            type: prop.type || 'string',
            defaultValue: prop.value || ''
          });
        });

        formData.fields = formFields;
        // 移除旧的FormData，添加新的
        const values = extensionElements.values?.filter(
          (el: any) => el.$type !== 'flowable:FormData'
        ) || [];
        values.push(formData);
        extensionElements.values = values;
      }

      console.log(`Updating form properties: ${validProperties.length} valid properties`);
      this.updateProperties(modeling, element, { extensionElements });
    } catch (error) {
      console.error('Failed to update form properties:', error);
    }
  }

  static addListener(modeling: any, element: any, type: string, listenerType: string, event: string, value: string) {
    const bpmnFactory = modeling.bpmnFactory;
    const businessObject = element.businessObject;
    let extensionElements = businessObject.extensionElements;

    if (!extensionElements) {
      extensionElements = bpmnFactory.create('bpmn:ExtensionElements');
    }

    const listener = bpmnFactory.create(`flowable:${type}Listener`, {
      event,
      [listenerType]: value
    });

    const values = extensionElements.values || [];
    values.push(listener);
    extensionElements.values = values;

    this.updateProperties(modeling, element, {
      extensionElements
    });
  }

  static removeListener(modeling: any, element: any, type: string, index: number) {
    const businessObject = element.businessObject;
    const extensionElements = businessObject.extensionElements;

    if (!extensionElements || !extensionElements.values) return;

    const listeners = extensionElements.values.filter((el: any) => is(el, `flowable:${type}Listener`));
    if (!listeners[index]) return;

    extensionElements.values = extensionElements.values.filter((el: any) => el !== listeners[index]);

    this.updateProperties(modeling, element, {
      extensionElements
    });
  }
}
